package com.lixian.mypro;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;

public class RecoderActivity extends AppCompatActivity implements SurfaceHolder.Callback, View.OnClickListener, MixStateCallBack {
    private Button start, stop, otherCamera;
    private MediaRecorder recorder;
    private CameraManager cameraManager;//相机服务
    private CameraDevice device;//当前相机对象
    private String frontId, backId;//前置，后置摄像头ID
    private SurfaceView surface;
    private PermissionUtil utils;
    private File root= Environment.getExternalStorageDirectory();
    private File outputfile;
    private Thread mixThread,audioThread;
    private String audioInputpath=new File(Environment.getExternalStorageDirectory(),"mypro/input.m4a").getAbsolutePath();
    private String outPutpath=new File(Environment.getExternalStorageDirectory(),"mypro/output.mp4").getAbsolutePath();
    private static final int START=1001;
    private static final int PROGRESS=1002;
    private static final int STOP=1003;
    private static final int ERROR=1004;
    private boolean isAudioHave=false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recoder);
        utils = PermissionUtil.getInstance();

        initView();

    }

    private void initRecoderParm() {
        recorder=new MediaRecorder();
        resetRecoder();
    }
    private ProgressDialog dialog;
    private void initView() {
        audioThread=new Thread(new CheckAudioSource());
        dialog=new ProgressDialog(this);
        dialog.setMessage("正在保存视频");
        dialog.setCancelable(false);
        start = (Button) findViewById(R.id.start);
        stop = (Button) findViewById(R.id.stop);
        audioThread.start();
        otherCamera = (Button) findViewById(R.id.other);
        start.setOnClickListener(this);
        stop.setOnClickListener(this);
        otherCamera.setOnClickListener(this);
        surface = (SurfaceView) findViewById(R.id.mSurface);
        surface.getHolder().addCallback(this);
    }
    class CheckAudioSource implements Runnable{

        @Override
        public void run() {
            try {
                InputStream open =
                        getAssets().open("input.m4a");
                int available = open.available();
                File audioFile = new File(audioInputpath);
                if (audioFile.length()==available) {
                    open.close();
                    Log.e("RecoderActivity","已经有音频文件");
                    isAudioHave=true;

                }else{
                    FileOutputStream stream = new FileOutputStream(audioFile);
                    int len=0;
                    byte[] buffer=new byte[1024];
                    while (-1!=(len=open.read(buffer))){
                        stream.write(buffer,0,len);
                        Log.e("RecoderActivity","写入音频文件");
                    }
                    Log.e("RecoderActivity","音频文件写入成功");
                    stream.flush();
                    stream.close();
                    open.close();
                    isAudioHave=true;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        initRecoderParm();
        cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
        try {
            getCameraInfo();
            openCamera(frontId);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (dialog!=null) {
            dialog.cancel();
        }
        if (device!=null) {
            device.close();
        }
        handler=null;
        mixHandler=null;
    }

    private void openCamera(String id) throws CameraAccessException {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ToastUtils.toast("相机无权限",RecoderActivity.this,2000);
            finish();
            return;
        }
        Log.e("RecoderActivity","开启摄像头ID="+id);
        cameraManager.openCamera(id,new CameraOpenStateCallback(),handler);
    }
    private Handler handler=new Handler();

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start:
                startRecoder();
                break;
            case R.id.stop:
                stopRecoder();
                break;
            case R.id.other:
                openotherCamera();
                break;
        }
    }
    private Handler mixHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what==ERROR) {
                if (dialog.isShowing()) {
                    dialog.hide();
                }
                ToastUtils.toast(msg.obj.toString(),RecoderActivity.this,2000);
            }else if (msg.what==STOP) {
                if (dialog.isShowing()) {
                    dialog.hide();
                }
                ToastUtils.toast("转码完成,路径="+outPutpath,RecoderActivity.this,2000);
            }

        }
    };
    private void stopRecoder() {
        start.setEnabled(true);
        stop.setEnabled(false);
        otherCamera.setEnabled(true);
        Log.e("RecoderActivity","结束录制"+outputfile.getAbsolutePath());
        try{
            recorder.stop();
            dialog.show();
            if (isAudioHave) {
                mixThread=new Thread(new MixTask(audioInputpath,this,outPutpath,outputfile.getAbsolutePath()));
                mixThread.start();
            }else{
                ToastUtils.toast("视频保存成功,未添加音频",RecoderActivity.this,2000);
                mixHandler.sendEmptyMessage(STOP);
            }

        }catch (Exception e){
            Log.e("RecoderActivity","录制时间过短");
        }


        resetRecoder();
        try {
            openCamera(device.getId());
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void resetRecoder() {
        recorder.reset();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

//        recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P));
        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//        recorder.setVideoEncodingBitRate(10000000);
        recorder.setVideoEncodingBitRate(2500000);
        recorder.setVideoFrameRate(60);

//        recorder.setVideoFrameRate(20);
        recorder.setVideoSize(1280, 720);
        recorder.setPreviewDisplay(surface.getHolder().getSurface());
        File dir = new File(root, "mypro");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String substring = UUID.randomUUID().toString().substring(0, 4);
        outputfile=new File(dir,substring+".mp4");
        recorder.setOutputFile(outputfile.getAbsolutePath());
        try {
            recorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void openotherCamera() {
        if (device==null) {
            return;
        }else {
            if (backId!=null&&device.getId().equals(frontId)) {
                closeCamera();
                try {
                    openCamera(backId);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }else if (frontId!=null&&device.getId().equals(backId)){
                closeCamera();
                try {
                    openCamera(frontId);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void closeCamera() {
        if (device!=null) {
            device.close();
        }
    }

    private void startRecoder() {
        //停止按钮可用，切换摄像头按钮不可用
        start.setEnabled(false);
        stop.setEnabled(true);
        Log.e("RecoderActivity","开始录制视频");
        otherCamera.setEnabled(false);
        recorder.start();
    }

    @Override
    public void onProgress() {
        Log.d("RecoderActivity","正在合成");
//        handler.sendEmptyMessage(PROGRESS);
    }

    @Override
    public void onSuccess() {
        Log.d("RecoderActivity","合成完毕");
        mixHandler.sendEmptyMessage(STOP);
    }

    @Override
    public void onmixStart() {
        Log.d("RecoderActivity","开始合成");
    }

    @Override
    public void onError(Exception e) {
        Message msg = Message.obtain();
        msg.what=ERROR;
        msg.obj=e.getMessage();
        handler.sendMessage(msg);
        Log.d("RecoderActivity","异常"+e.getMessage());
    }

    class CameraOpenStateCallback extends CameraDevice.StateCallback{

        @Override
        public void onOpened(CameraDevice camera) {
            RecoderActivity.this.device=camera;
            try {
                startPreview(camera);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(CameraDevice camera) {
            try{
                camera.close();
            }catch (Exception e){

            }

            device=null;
        }

        @Override
        public void onError(CameraDevice camera, int error) {

        }
    }
    private CameraCaptureSession session;//当前相机会话
    private void startPreview(CameraDevice camera) throws CameraAccessException {
        final CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
        builder.addTarget(recorder.getSurface());
        builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        builder.addTarget(surface.getHolder().getSurface());
        camera.createCaptureSession(Arrays.asList( surface.getHolder().getSurface(),recorder.getSurface()), new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                RecoderActivity.this.session=session;
                CaptureRequest request = builder.build();
                try {
                    session.setRepeatingRequest(request,null,null);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {

            }
        },handler);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    public void getCameraInfo() throws CameraAccessException {
        if (cameraManager==null) {
            return;
        }
        String[] idList = cameraManager.getCameraIdList();
        for (int i = 0; i < idList.length; i++) {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(idList[i]);
            Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
            if (facing== CameraCharacteristics.LENS_FACING_FRONT) {
                //前置摄像头
                frontId=idList[i];
            }else if(facing==CameraCharacteristics.LENS_FACING_BACK){
                backId=idList[i];
            }
        }
    }
}
